﻿#ifndef _CODE_VERIFY_H_H
#define	_CODE_VERIFY_H_H

#include <stdint.h>
#include <pincfg.h>
#include <dataproc.h>
#include <swap.h>
#include "mbedtls/des.h"

#ifdef	__cplusplus
extern "C" {
#endif

/*******************************************************************************
* @brief	采用DES加密算法制作密码本
*			分组为2字的单元，即每组8字节
********************************************************************************
* 操作应保持在 alloc 和 free 之间
* enc_gen 和 dec_gen 为独立运算，结果暂存des_out;
* enc_gen 取元数据区数据进行加密	- 加密
* dec_gen 取加密区数据进行解密		- 解密
* rom_val_get 前要先调用对应的 rom_addr_make
* app 执行完 jiamihandle后应擦除该函数。然后填充返回指令
*******************************************************************************/
#define CVF_FUN_ADDR		0x08004000UL	// 	加密函数地址
#define CVF_UUID_ID			0x1FFFF7E8UL	// 	UUID地址
#define CVF_ENC_ADDR		0x0807F800UL	// 	加密数据地址		扇区对齐
#define CVF_SRC_ADDR		0x08002000UL	//	元数据地址			字对齐	
#define CFV_CODE_LEN		1024			//	密码本长度，字节数
	
/*******************************************************************************
* @brief	数据结构
*******************************************************************************/
typedef struct
{
	uint32_t addr;
	uint32_t key[2];
	uint32_t out[2];
	mbedtls_des_context ctx;
} cvf_ctr_type;

/*******************************************************************************
* @brief	过程控制
*******************************************************************************/
#define cvf_check_alloc()		cvf_ctr_type cvf; cvf.addr=0

// 键值获取
#define	cvf_key_set(gp)											\
	cvf.key[0] = inpw(cvf.addr) * (gp + 11);					\
	cvf.key[0] +=  inpw(cvf.addr + 4) * 13;						\
	cvf.key[1] = inpw(cvf.addr) * (gp + 17);					\
	cvf.key[1] +=  inpw(cvf.addr + 8) * 19;						\
	swap_bit_map_u8(cvf.key, cvf.key);

// 获取指定分组的加密值，结果暂存 cvf.out	
#define cvf_enc_gen(gp)											\
	cvf.addr = code_set_ub(cvf.addr, byte_ub(CVF_UUID_ID));		\
	cvf.addr = code_set_lb(cvf.addr, byte_lb(CVF_UUID_ID));		\
	cvf.addr = code_set_mb(cvf.addr, byte_mb(CVF_UUID_ID));		\
	cvf.addr = code_set_hb(cvf.addr, byte_hb(CVF_UUID_ID));		\
	cvf_key_set(gp)												\
	cvf.addr = code_set_lb(cvf.addr, byte_lb(CVF_SRC_ADDR));	\
	cvf.addr = code_set_hb(cvf.addr, byte_hb(CVF_SRC_ADDR));	\
	cvf.addr = code_set_mb(cvf.addr, byte_mb(CVF_SRC_ADDR));	\
	cvf.addr = code_set_ub(cvf.addr, byte_ub(CVF_SRC_ADDR));	\
	mbedtls_des_init(&cvf.ctx);									\
	mbedtls_des_setkey_enc(&cvf.ctx, (void *)cvf.key);			\
	mbedtls_des_crypt_ecb(&cvf.ctx, (const void *)(cvf.addr + gp * 8), (void *)cvf.out); \
	mbedtls_des_free(&cvf.ctx);

// 获取指定分组的解密值，结果暂存 cvf.out
#define cvf_dec_gen(gp)											\
	cvf.addr = code_set_hb(cvf.addr, byte_hb(CVF_UUID_ID));		\
	cvf.addr = code_set_mb(cvf.addr, byte_mb(CVF_UUID_ID));		\
	cvf.addr = code_set_ub(cvf.addr, byte_ub(CVF_UUID_ID));		\
	cvf.addr = code_set_lb(cvf.addr, byte_lb(CVF_UUID_ID));		\
	cvf_key_set(gp)												\
	cvf.addr = code_set_mb(cvf.addr, byte_mb(CVF_ENC_ADDR));	\
	cvf.addr = code_set_hb(cvf.addr, byte_hb(CVF_ENC_ADDR));	\
	cvf.addr = code_set_lb(cvf.addr, byte_lb(CVF_ENC_ADDR));	\
	cvf.addr = code_set_ub(cvf.addr, byte_ub(CVF_ENC_ADDR));	\
	mbedtls_des_init(&cvf.ctx);									\
	mbedtls_des_setkey_dec(&cvf.ctx, (void*)cvf.key);			\
	mbedtls_des_crypt_ecb(&cvf.ctx, (const void *)(cvf.addr + gp * 8), (void*)cvf.out); \
	mbedtls_des_free(&cvf.ctx);
	
// 制作加密区指定分组-元素的地址
#define cvf_enc_rom_addr_make(gp, coil)							\
	cvf.addr = code_set_hb(cvf.addr, byte_hb(CVF_ENC_ADDR));	\
	cvf.addr = code_set_lb(cvf.addr, byte_lb(CVF_ENC_ADDR));	\
	cvf.addr = code_set_mb(cvf.addr, byte_mb(CVF_ENC_ADDR));	\
	cvf.addr = code_set_ub(cvf.addr, byte_ub(CVF_ENC_ADDR));	\
	cvf.addr += gp * 8;	cvf.addr += coil * 4;

// 制作元数据区指定分组-元素的地址
#define cvf_src_rom_addr_make(gp, coil)							\
	cvf.addr = code_set_lb(cvf.addr, byte_lb(CVF_SRC_ADDR));	\
	cvf.addr = code_set_mb(cvf.addr, byte_mb(CVF_SRC_ADDR));	\
	cvf.addr = code_set_ub(cvf.addr, byte_ub(CVF_SRC_ADDR));	\
	cvf.addr = code_set_hb(cvf.addr, byte_hb(CVF_SRC_ADDR));	\
	cvf.addr += gp * 8;	cvf.addr += coil * 4;
		
#define cvf_rom_val_get()	inpw(cvf.addr)
		
// 清除堆栈内存数据
#define cvf_free() memset(&cvf, 0, sizeof(cvf));
	
// 加密接口
void cvf_handle(void);

#ifdef	__cplusplus
}
#endif

#endif	/* _CODE_VERIFY_H_H */
